using System;
using System.Drawing;
using System.Globalization;
using PickGold.Charting;

namespace PickGold.Charting.ChartTypes
{
	internal class BubbleChart : PointChart
	{
		private double _maxAll;
		private float _maxBubleSize;
		private double _maxPossibleBubbleSize;
		private double _minAll;
		private float _minBubleSize;
		private double _minPossibleBubbleSize;
		private bool _scaleDetected;
		private double _valueDiff;
		private double _valueScale;

		public BubbleChart()
			: base(true)
		{
			this._maxPossibleBubbleSize = 15.0;
			this._minPossibleBubbleSize = 3.0;
			this._minAll = double.MaxValue;
			this._maxAll = double.MinValue;
			this._valueScale = 1.0;
		}

		internal static double AxisScaleBubbleSize(CommonElements common, ChartArea area, double value, bool yValue)
		{
			double num7;
			double num8;
			double maxValue = double.MaxValue;
			double minValue = double.MinValue;
			double num3 = 15.0;
			double num4 = 3.0;
			foreach (Series series in common.DataManager.Series)
			{
				if (((string.Compare(series.ChartTypeName, "Bubble", StringComparison.OrdinalIgnoreCase) != 0) || !(series.ChartArea == area.Name)) || !series.IsVisible())
				{
					continue;
				}
				if (series.IsCustomPropertySet("BubbleScaleMin"))
				{
					maxValue = Math.Min(maxValue, CommonElements.ParseDouble(series["BubbleScaleMin"]));
				}
				if (series.IsCustomPropertySet("BubbleScaleMax"))
				{
					minValue = Math.Max(minValue, CommonElements.ParseDouble(series["BubbleScaleMax"]));
				}
				if (series.IsCustomPropertySet("BubbleMaxSize"))
				{
					num3 = CommonElements.ParseDouble(series["BubbleMaxSize"]);
					if ((num3 < 0.0) || (num3 > 100.0))
					{
						throw new ArgumentException(SR.ExceptionCustomAttributeIsNotInRange0to100("BubbleMaxSize"));
					}
				}
				if (series.IsCustomPropertySet("BubbleUseSizeForLabel") && (string.Compare(series["BubbleUseSizeForLabel"], "true", StringComparison.OrdinalIgnoreCase) == 0))
				{
					break;
				}
			}
			double num9 = double.MaxValue;
			double num10 = double.MinValue;
			double num11 = double.MaxValue;
			double num12 = double.MinValue;
			foreach (Series series2 in common.DataManager.Series)
			{
				if (((string.Compare(series2.ChartTypeName, "Bubble", StringComparison.OrdinalIgnoreCase) == 0) && (series2.ChartArea == area.Name)) && series2.IsVisible())
				{
					foreach (DataPoint point in series2.Points)
					{
						if (!point.IsEmpty)
						{
							num11 = Math.Min(num11, point.YValues[1]);
							num12 = Math.Max(num12, point.YValues[1]);
							if (yValue)
							{
								num9 = Math.Min(num9, point.YValues[0]);
								num10 = Math.Max(num10, point.YValues[0]);
							}
							else
							{
								num9 = Math.Min(num9, point.XValue);
								num10 = Math.Max(num10, point.XValue);
							}
						}
					}
					continue;
				}
			}
			if (maxValue == double.MaxValue)
			{
				maxValue = num11;
			}
			if (minValue == double.MinValue)
			{
				minValue = num12;
			}
			float num5 = (float)((num10 - num9) / (100.0 / num3));
			float num6 = (float)((num10 - num9) / (100.0 / num4));
			if (minValue == maxValue)
			{
				num7 = 1.0;
				num8 = maxValue - ((num5 - num6) / 2f);
			}
			else
			{
				num7 = ((double)(num5 - num6)) / (minValue - maxValue);
				num8 = maxValue;
			}
			if (value > minValue)
			{
				return 0.0;
			}
			if (value < maxValue)
			{
				return 0.0;
			}
			return (double)(((float)((value - num8) * num7)) + num6);
		}

		internal static double GetBubbleMaxSize(ChartArea area)
		{
			double num = 15.0;
			foreach (Series series in area.Common.DataManager.Series)
			{
				if (((string.Compare(series.ChartTypeName, "Bubble", StringComparison.OrdinalIgnoreCase) == 0) && (series.ChartArea == area.Name)) && (series.IsVisible() && series.IsCustomPropertySet("BubbleMaxSize")))
				{
					num = CommonElements.ParseDouble(series["BubbleMaxSize"]);
					if ((num < 0.0) || (num > 100.0))
					{
						throw new ArgumentException(SR.ExceptionCustomAttributeIsNotInRange0to100("BubbleMaxSize"));
					}
				}
			}
			return (num / 100.0);
		}

		public override Image GetImage(ChartTypeRegistry registry)
		{
			return (Image)registry.ResourceManager.GetObject(this.Name + "ChartType");
		}

		protected override int GetMarkerBorderSize(DataPointCustomProperties point)
		{
			if (point.series != null)
			{
				return point.series.BorderWidth;
			}
			return 1;
		}

		protected override SizeF GetMarkerSize(ChartGraphics graph, CommonElements common, ChartArea area, DataPoint point, int markerSize, string markerImage)
		{
			if (point.YValues.Length < this.YValuesPerPoint)
			{
				throw new InvalidOperationException(SR.ExceptionChartTypeRequiresYValues(this.Name, this.YValuesPerPoint.ToString(CultureInfo.InvariantCulture)));
			}
			SizeF ef = new SizeF((float)markerSize, (float)markerSize);
			if ((graph != null) && (graph.Graphics != null))
			{
				ef.Width = (markerSize * graph.Graphics.DpiX) / 96f;
				ef.Height = (markerSize * graph.Graphics.DpiY) / 96f;
			}
			if ((point.series.YValuesPerPoint > 1) && !point.IsEmpty)
			{
				ef.Width = this.ScaleBubbleSize(graph, common, area, point.YValues[1]);
				ef.Height = this.ScaleBubbleSize(graph, common, area, point.YValues[1]);
			}
			return ef;
		}

		protected override void ProcessChartType(bool selection, ChartGraphics graph, CommonElements common, ChartArea area, Series seriesToDraw)
		{
			this._scaleDetected = false;
			base.ProcessChartType(selection, graph, common, area, seriesToDraw);
		}

		private float ScaleBubbleSize(ChartGraphics graph, CommonElements common, ChartArea area, double value)
		{
			if (!this._scaleDetected)
			{
				this._minAll = double.MaxValue;
				this._maxAll = double.MinValue;
				foreach (Series series in common.DataManager.Series)
				{
					if (((string.Compare(series.ChartTypeName, this.Name, true, CultureInfo.CurrentCulture) != 0) || !(series.ChartArea == area.Name)) || !series.IsVisible())
					{
						continue;
					}
					if (series.IsCustomPropertySet("BubbleScaleMin"))
					{
						this._minAll = Math.Min(this._minAll, CommonElements.ParseDouble(series["BubbleScaleMin"]));
					}
					if (series.IsCustomPropertySet("BubbleScaleMax"))
					{
						this._maxAll = Math.Max(this._maxAll, CommonElements.ParseDouble(series["BubbleScaleMax"]));
					}
					if (series.IsCustomPropertySet("BubbleMaxSize"))
					{
						this._maxPossibleBubbleSize = CommonElements.ParseDouble(series["BubbleMaxSize"]);
						if ((this._maxPossibleBubbleSize < 0.0) || (this._maxPossibleBubbleSize > 100.0))
						{
							throw new ArgumentException(SR.ExceptionCustomAttributeIsNotInRange0to100("BubbleMaxSize"));
						}
					}
					if (series.IsCustomPropertySet("BubbleMinSize"))
					{
						this._minPossibleBubbleSize = CommonElements.ParseDouble(series["BubbleMinSize"]);
						if ((this._minPossibleBubbleSize < 0.0) || (this._minPossibleBubbleSize > 100.0))
						{
							throw new ArgumentException(SR.ExceptionCustomAttributeIsNotInRange0to100("BubbleMinSize"));
						}
					}
					base.labelYValueIndex = 0;
					if (series.IsCustomPropertySet("BubbleUseSizeForLabel") && (string.Compare(series["BubbleUseSizeForLabel"], "true", StringComparison.OrdinalIgnoreCase) == 0))
					{
						base.labelYValueIndex = 1;
						break;
					}
				}
				if ((this._minAll == double.MaxValue) || (this._maxAll == double.MinValue))
				{
					double maxValue = double.MaxValue;
					double minValue = double.MinValue;
					foreach (Series series2 in common.DataManager.Series)
					{
						if (((series2.ChartTypeName == this.Name) && (series2.ChartArea == area.Name)) && series2.IsVisible())
						{
							foreach (DataPoint point in series2.Points)
							{
								if (!point.IsEmpty)
								{
									if (point.YValues.Length < this.YValuesPerPoint)
									{
										throw new InvalidOperationException(SR.ExceptionChartTypeRequiresYValues(this.Name, this.YValuesPerPoint.ToString(CultureInfo.InvariantCulture)));
									}
									maxValue = Math.Min(maxValue, point.YValues[1]);
									minValue = Math.Max(minValue, point.YValues[1]);
								}
							}
							continue;
						}
					}
					if (this._minAll == double.MaxValue)
					{
						this._minAll = maxValue;
					}
					if (this._maxAll == double.MinValue)
					{
						this._maxAll = minValue;
					}
				}
				SizeF absoluteSize = graph.GetAbsoluteSize(area.PlotAreaPosition.Size);
				this._maxBubleSize = (float)(((double)Math.Min(absoluteSize.Width, absoluteSize.Height)) / (100.0 / this._maxPossibleBubbleSize));
				this._minBubleSize = (float)(((double)Math.Min(absoluteSize.Width, absoluteSize.Height)) / (100.0 / this._minPossibleBubbleSize));
				if (this._maxAll == this._minAll)
				{
					this._valueScale = 1.0;
					this._valueDiff = this._minAll - ((this._maxBubleSize - this._minBubleSize) / 2f);
				}
				else
				{
					this._valueScale = ((double)(this._maxBubleSize - this._minBubleSize)) / (this._maxAll - this._minAll);
					this._valueDiff = this._minAll;
				}
				this._scaleDetected = true;
			}
			if (value > this._maxAll)
			{
				return 0f;
			}
			if (value < this._minAll)
			{
				return 0f;
			}
			return (((float)((value - this._valueDiff) * this._valueScale)) + this._minBubleSize);
		}

		public override string Name
		{
			get
			{
				return "Bubble";
			}
		}

		public override bool SecondYScale
		{
			get
			{
				return true;
			}
		}

		public override int YValuesPerPoint
		{
			get
			{
				return 2;
			}
		}
	}
}

